package cn.bby.query.server.domain.agg.metadata.entity;

import cn.bby.query.base.model.dto.InterfaceMetaInfo;
import cn.bby.query.server.domain.agg.metadata.entity.valobj.ColumnInfo;
import cn.bby.query.server.domain.agg.metadata.entity.valobj.TableInfo;
import cn.bby.query.server.domain.share.constant.InterfaceStatus;
import cn.hutool.core.bean.BeanUtil;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author ben
 * @since 2025/4/20 23:29
 */
@Data
@NoArgsConstructor
public class InterfaceInfo {
    /**
     * 接口id
     */
    private Long interfaceId;
    /**
     * 服务名称
     */
    private String serverName;
    /**
     * 接口描述
     */
    private String description;
    /**
     * 版本号
     */
    private String version;

    /**
     * 源表
     */
    private Long mainTableId;

    /**
     * 接口名
     */
    private String interfaceName;

    /**
     * 接口路径
     */
    private String methodPath;

    /**
     * 主键db字段名
     */
    private String primaryColumn;

    /**
     * 主键字段名
     */
    private String primaryField;

    /**
     * 主键字段类型
     */
    private String primaryColumnType;

    /**
     * 主键字段是否自增
     */
    private Boolean isPrimaryIncrement;

    /**
     * 创建时间db字段名
     */
    private String createTimeColumn;

    /**
     * 创建时间字段名
     */
    private String createTimeField;

    /**
     * 地址
     */
    private String baseUrl;

    /**
     * 状态：LOADING-加载中，READY-就绪
     * @see InterfaceStatus
     */
    private String status;

    /**
     * 重试次数
     */
    private Long errRetryTimes;
    /**
     * 字段信息
     */
    private List<ColumnInfo> columns;
    /**
     * 字段信息
     */
    private List<TableInfo> subTables;

    public InterfaceInfo(Long interfaceId, InterfaceMetaInfo interfaceMetaInfo) {
        BeanUtil.copyProperties(interfaceMetaInfo, this);
        setInterfaceId(interfaceId);
    }

    private Map<Long, TableInfo> tableMetaInfoMap;
    private Map<Long, List<String>> tableIdCompColMap;
    private Map<Long, List<ColumnInfo>> tableIdSimpColsMap;
    private Map<String, ColumnInfo> fieldColumnMap;
    private Map<Long, ColumnInfo> tableIdPriColumnMap;

    public TableInfo getSubTableById(Long tableId) {
        if (tableMetaInfoMap == null) {
            tableMetaInfoMap = getSubTables()
                    .stream()
                    .collect(
                            Collectors.toMap(TableInfo::getTableId, Function.identity())
                    );
        }
        return tableMetaInfoMap.get(tableId);
    }

    public List<String> getCompColsByTableId(Long tableId) {
        if (tableIdCompColMap == null) {
            tableIdCompColMap = getColumns()
                    .stream()
                    .filter(ColumnInfo::getIsComplex)
                    .collect(
                            Collectors.groupingBy(ColumnInfo::getTableId,
                                    Collectors.mapping(ColumnInfo::getLinkCol, Collectors.toCollection(HashSet::new)))
                    ).entrySet()
                    .stream()
                    .collect(Collectors.toMap(
                            Map.Entry::getKey,
                            e -> new ArrayList<>(e.getValue())
                    ));
        }
        return tableIdCompColMap.get(tableId);
    }

    public ColumnInfo getColumnByFieldName(String field) {
        if (fieldColumnMap == null) {
            fieldColumnMap = getColumns()
                    .stream()
                    .collect(
                            Collectors.toMap(ColumnInfo::getFieldName, Function.identity())
                    );
        }
        return fieldColumnMap.get(field);
    }

    public List<ColumnInfo> getSimpColsByTableId(Long tableId) {
        if (tableIdSimpColsMap == null) {
            tableIdSimpColsMap = getColumns()
                    .stream()
                    .filter(column -> !column.getIsComplex() && !column.getIsConstant())
                    .collect(
                            Collectors.groupingBy(ColumnInfo::getTableId,
                                    Collectors.mapping(Function.identity(), Collectors.toList())
                            ));
        }
        return tableIdSimpColsMap.get(tableId);
    }

    public ColumnInfo getIdentityColumnByTableId(Long tableId) {
        if (tableIdPriColumnMap == null) {
            tableIdPriColumnMap = getColumns()
                    .stream()
                    .filter(ColumnInfo::getIsComplex)
                    .collect(
                            Collectors.toMap(ColumnInfo::getTableId, Function.identity(), (o1, o2) -> o1)
                    );
        }
        return tableIdPriColumnMap.get(tableId);
    }

    public void initCache() {
        getColumnByFieldName("id");
        getCompColsByTableId(1L);
        getIdentityColumnByTableId(1L);
        getSubTableById(1L);
        getSimpColsByTableId(1L);
    }
}
